#include "..\System.h"

///<summary>
/// _getInstanceByType
///</summary>
public System_Object *_getInstanceByType(System_Object *t, System_Type *type, bool throwOnNull, void **_ref)
{
	System_Type *tType = t->__type;
	System_Object *p = t->__parent;
	//+ types do not match, search required
	if (t->__type != type)
	{
		//+ rebase t if interface, can not search on interfaces
		if ((tType->__flags & _TypeFlags_Interface) == _TypeFlags_Interface)
			t = p;
	//+ types already match, return
	} else {
		if (_ref != null)
			*_ref = ((tType->__flags & _TypeFlags_Interface) != _TypeFlags_Interface ? t : p);
		return t;
	}
	//+ interface
	if ((type->__flags & _TypeFlags_Interface) == _TypeFlags_Interface)
	{
		//+ search descendants
		for (; (t != null); t = t->__next)
		{
			System_Object *t2;
			for (t2 = (System_Object *)t->__interfaces; (t2 != null); t2 = t2->__next)
			{
				if (t2->__type == type)
				{
					if (_ref != null)
						*_ref = t;
					return t2;
				}
			}
		}
		if (p != null)
		{
			//+ search ancestors
			for (; (p != null); p = p->__parent)
			{
				System_Object *t2;
				for (t2 = (System_Object *)p->__interfaces; (t2 != null); t2 = t2->__next)
				{
					if (t2->__type == type)
					{
						if (_ref != null)
							*_ref = p;
						return t2;
					}
				}
			}
		}
	// class
	} else {
		//+ search descendants
		for (; (t != null); t = t->__next)
		{
			if (t->__type == type)
			{
				if (_ref != null)
					*_ref = t;
				return t;
			}
		}
		if (p != null)
		{
			//+ search ancestors
			for (; (p != null); p = p->__parent)
			{
				if (p->__type == type)
				{
					if (_ref != null)
						*_ref = p;
					return p;
				}
			}
		}
	}
	if (throwOnNull == false)
	{
		return (System_Object *)null;
	}
	throw(UnableToFindInstance);
#ifdef __CUDACC__
	return (System_Object *)null;
#endif
}
